/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "core/几何计算/多边形.h"
#include "面/几何模型生成.h"


void f_polygon_构建平面(vec2 size, uvec2 细分, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, t_面顶点索引& index) {
	细分 = max(细分, { 1,1 });

	vec2 offset = size / 细分;
	uint32 offsetIndex = 0;

	index.resize(细分.y * 细分.x);
	std::vector<uint32>* p_Index = index.data();
	
	
	for (uint32 y = 0; y < 细分.y; ++y) {
		uint32 跨行 = (细分.x + 1) * (y + 1);
		uint32 当前行 = y * (细分.x + 1);
	
		for (uint32 x = 0; x < 细分.x; ++x) {
			p_Index[offsetIndex] = { 
									当前行 + x,
									当前行 + x + 1,
									跨行 + x + 1,
									跨行 + x,
									};
			++offsetIndex;
		}
	}

	细分.x += 1;
	细分.y += 1;
	uint32 顶点数量 = 细分.x * 细分.y;
	V.resize(顶点数量);
	N.resize(顶点数量);
	uv.resize(顶点数量);

	auto* p_Vert = V.data();
	auto* p_Normal = N.data();
	auto* p_UV = uv.data();

	offsetIndex = 0;
	vec3 负方向偏移 = { size.x * 0.5f, 0.0f, size.y * 0.5f };
	for (uint32 y = 0; y < 细分.y; ++y) {
		for (uint32 x = 0; x < 细分.x; ++x) {
			vec3 顶点 = {};
			vec2 UV;

			顶点.x = x * offset.x;
			顶点.z = y * offset.y;
			p_Vert[offsetIndex] = 顶点 - 负方向偏移;
			p_Normal[offsetIndex] = {0,1,0};

			UV.x = x / 细分.x;
			UV.y = y / 细分.y;
			p_UV[offsetIndex] = UV;

			++offsetIndex;
		}
	}
}

void f_polygon_构建方体(vec3 size, uvec3 细分, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, t_面顶点索引& index) {
	uint32 num = (细分.x + 1) * (细分.y + 1) * (细分.z + 1);
	V.resize(num);
	N.resize(num);

	uv.resize(V.size());
	vec2* uv_ptr = uv.data();


	size *= 0.5;
	V = {
		{-size.x, -size.y, -size.z},	//0
		{-size.x, size.y, -size.z},		//1
		{size.x, size.y, -size.z},		//2
		{size.x, -size.y, -size.z},		//3

		{-size.x, -size.y, size.z},		//4
		{-size.x, size.y, size.z},		//5
		{size.x, size.y, size.z},		//6
		{size.x, -size.y, size.z},		//7
	};

	N.resize(8);
	for (uint32 i = 0; i < 8; ++i) {
		N[i] = vec_normalize2(V[i]);
	}

	index.resize(6);
	index[0] = { 5, 4, 7, 6 };		//+Z
	index[1] = { 0, 1, 2, 3 };		//-Z
	index[2] = { 2, 6, 7, 3 };		//+X
	index[3] = { 5, 1, 0, 4 };		//-X
	index[4] = { 5, 6, 2, 1 };		//+Y
	index[5] = { 0, 3, 7, 4 };		//-Y


}

void f_polygon_构建圆柱(vec2 size, uvec2 细分, DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, t_面顶点索引& index) {
	细分.x = DEF_Max(细分.x, 3);
	细分.y = DEF_Max(细分.y, 1);

	size.x = DEF_Max(size.x, 0);
	size.y = DEF_Max(size.y, 0);



	std::vector<vec3> 圆(细分.x);
	f_graph_计算圆坐标3({0, size.y*0.5f, 0 }, size.x, 细分.x, 圆.data(), E_轴向::e_Y);

	std::vector<uint32> 圆索引A = f_Range<uint32>(0, 细分.x);
	圆索引A.push_back(0);

	uint32 num = 细分.x * 2 * 细分.y;
	v.clear();
	n.clear();
	uv.clear();
	index.clear();

	float32 上下步进 = size.y / 细分.y;
	for (uint32 i = 0; i <= 细分.y; ++i) {

		v.insert(v.end(), 圆.begin(), 圆.end());
		n.insert(n.end(), 圆.begin(), 圆.end());

		for (auto& e : 圆) e.y -= 上下步进;
	}
	v.push_back(vec3{ 0, size.y*0.5f, 0 });
	v.push_back(vec3{ 0, -size.y*0.5f, 0 });
	n.push_back({ 0,1,0 });
	n.push_back({0,-1,0});



	uv.resize(v.size());

	uint32 顶端顶点索引 = v.size() - 2;
	uint32 底端顶点索引 = v.size() - 1;


	index.reserve(细分.x * 3 * 2 + 细分.x * 6 * 细分.y);

	for (uint32 i = 0; i < 细分.x; ++i) {
		index.push_back(
			{
				圆索引A[i],
				顶端顶点索引,
				圆索引A[i + 1],
			}
		);
	}

	uint32 偏移A;
	uint32 偏移B;
	for (uint32 y = 0; y < 细分.y; ++y) {
		偏移A = 圆.size() * (y);
		偏移B = 圆.size() * (y + 1);

		for (uint32 i = 0; i < 细分.x; ++i) {
			index.push_back(
				{
					偏移A + 圆索引A[i],
					偏移B + 圆索引A[i],
					偏移B + 圆索引A[i + 1],
					偏移A + 圆索引A[i + 1]
				}
			);
		}
	}

	偏移A = 圆.size() * 细分.y;
	for (uint32 i = 0; i < 细分.x; ++i) {
		index.push_back(
			{
				偏移A + 圆索引A[i],
				底端顶点索引,
				偏移A + 圆索引A[i + 1],
			}
		);
	}

}

void f_polygon_构建锥体(vec2 size, uint32 细分, DEF_3Fs& v, DEF_3Fs& n, DEF_2Fs& uv, t_面顶点索引& index) {
	细分 = DEF_Max(细分, 3);

	size.x = DEF_Max(size.x, 0);
	size.y = DEF_Max(size.y, 0);

	v.resize(细分);
	f_graph_计算圆坐标3({ 0, 0, 0 }, size.x, 细分, v.data(), E_轴向::e_Y);

	v.insert(v.begin(), vec3{});
	v.push_back({0, size.y, 0});

	uv.resize(v.size());
	n.resize(v.size());
	index.clear();

	for (uint32 i = 0; i < 细分; ++i) {
		index.push_back({i + 1, 0, i + 2});
	}
	index.back().back() = 1;
	

	uint32 end = v.size() - 1;
	for (uint32 i = 0; i < 细分; ++i) {
		index.push_back({i + 1, end, i + 2});
	}
	index.back().back() = 1;
}

void f_polygon_构建球体(uint32 经度细分, uint32 维度细分, float32 半径, DEF_3Fs& V, DEF_3Fs& N, DEF_2Fs& uv, t_面顶点索引& I) {
	经度细分 = DEF_Max(经度细分, 3);
	维度细分 = DEF_Max(维度细分, 2);

	V.resize(经度细分 * (维度细分-1) + 2);
	N.resize(经度细分 * (维度细分-1) + 2);
	I.clear();

	

	uv.resize(V.size());
	uint32 端点偏移 = 1;
	vec2* uv_ptr = uv.data();


	//底部顶点
	vec3_填充(&V[0], 0.0, -半径, 0.0);
	//顶部顶点
	vec3_填充(&V[经度细分 * (维度细分-1) + 1], 0.0, 半径, 0.0);


	vec3_填充(&N[0], 0.0, -1.0, 0.0);
	vec3_填充(&N[经度细分 * (维度细分-1) + 1], 0.0, 1.0, 0.0);


	S_Tranform 变换 = f_tranformIdentity();
	矩阵_创建缩放矩阵v(缩放矩阵, (float32*)&变换.scale);


	vec4	NewNormal = { 0.0, 1.0, 0.0, 0.0 };

	float32	坐标Z[4] = { 0.0, -半径, 0.0, 1.0 };
	float32	Normal[4] = { 0.0, -1.0, 0.0, 1.0 };
	float32	变换后坐标[4] = { 0.0, 0.0, 0.0 , 0.0 };
	矩阵_创建移动矩阵v(移动矩阵, 坐标Z);


	float32 维度步进 = 180.0f / (float32)维度细分;
	float32 进度步进 = 360.0f / (float32)经度细分;

	for (uint16 纬度 = 0; 纬度 < 维度细分 - 1; ++纬度) {
		float32 当前维度 = 维度步进 * (float32)(纬度 + 1);

		矩阵_创建X旋转矩阵(X旋转矩阵, 当前维度);
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint16 id = 纬度 * 经度细分 + 经度 + 端点偏移;
			float32 当前经度 = 进度步进 * (float32)(经度);

			矩阵_创建Y旋转矩阵(Y旋转矩阵, 当前经度);
			矩阵_创建单位矩阵4X4(变换矩阵);

			Mat4X4_相乘(&变换矩阵, &Y旋转矩阵);
			Mat4X4_相乘(&变换矩阵, &X旋转矩阵);


			vec3_填充(变换后坐标, 0.0);
			vec4_填充(&NewNormal, 0.0);
			MAT变换坐标4(&变换矩阵, 坐标Z, 变换后坐标);
			MAT变换坐标4(&变换矩阵, Normal, &NewNormal);


			vec3_填充(&V[id], (vec4*)变换后坐标);
			vec3_填充(&N[id], &NewNormal);
			uv_ptr[id].x = 纬度;
			uv_ptr[id].y = 经度;
		}
	}


	I.reserve( (经度细分 * (维度细分-2)) + (经度细分*6) );
	//auto 索引 = I.data();

	//底部盖
	//索引[0] = 0;
	uint32 V1 = 0;
	uint32 V2 = 1;
	uint32 V3 = 2;
	uint32 V4 = 0;
	uint32 index = 0;

	//底部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		I.push_back({V1, V2, V3});
		
		V2 += 1;
		V3 += 1; if (V3 >= 经度细分 + 1) V3 = 1;
	}

	for (uint16 纬度 = 0; 纬度 < 维度细分 - 2; ++纬度) {
		for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
			uint32 idL1 = 纬度 * 经度细分 + 经度 + 端点偏移;
			uint32 idL2 = (纬度 + 1) * 经度细分 + 经度 + 端点偏移;


			V1 = idL1; V2 = idL2; V3 = idL2 + 1; V4 = idL1 + 1; 

			if (经度 + 1 >= 经度细分) {
				V3 = (纬度 + 1) * 经度细分 + 端点偏移;
				V4 = 纬度 * 经度细分 + 端点偏移;
			}

			I.push_back({V1, V2, V3, V4});
		}
	}

	V1 = 经度细分 * (维度细分-1) + 端点偏移;
	//顶部盖
	for (uint16 经度 = 0; 经度 < 经度细分; ++经度) {
		uint32 idL1 = (维度细分 - 2) * 经度细分 + 经度 + 端点偏移;
		V2 = idL1; 

		if (经度 + 1 >= 经度细分) V3 = (维度细分 - 2) * 经度细分 + 端点偏移;
		else V3 = idL1 + 1;

		I.push_back({V2, V3, V3});
	}
}



















